﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using KingRoad.EPM.PersonnelLogEntity;
using NPOI.SS.UserModel;
using ExcelImportValidationAttribute = KingRoad.EPM.PersonnelLogEntity.ExcelImportValidationAttribute;
//KingRoad.EPM.Web.Areas.SafetyConstruction.SafetyConstructionFramework.Common
namespace KingRoad.EPM.Web.Areas.CompletionMaterials.CompletionMaterialsFramework.Common
{

    public static class ExcelImportValidation
    {
        public static Tuple<bool, string> Validation<T>(ISheet sheet) where T : BaseEntity
        {

            Dictionary<PropertyInfo, ExcelImportValidationAttribute> dicPropertyAttribute = new Dictionary<PropertyInfo, ExcelImportValidationAttribute>();

            var properties = typeof(T).GetProperties();

            properties.ToList().ForEach(f =>
            {
                object[] customAttributes = f.GetCustomAttributes(typeof(ExcelImportValidationAttribute), false);
                if (customAttributes.Any())
                {
                    var excelAttribute = customAttributes[0] as ExcelImportValidationAttribute;
                    dicPropertyAttribute.Add(f, excelAttribute);
                }
            });
            var ret1 = ValidationColumn(dicPropertyAttribute, sheet);
            if (!ret1.Item1)
                return ret1;
            var ret2 = ValidationDatas(dicPropertyAttribute, sheet);
            if (!ret2.Item1)
                return ret2;

            return new Tuple<bool, string>(true, "");
        }

        private static Tuple<bool, string> ValidationColumn(Dictionary<PropertyInfo, ExcelImportValidationAttribute> dic, ISheet sheet)
        {
            IRow headerRow = sheet.GetRow(0);

            foreach (KeyValuePair<PropertyInfo, ExcelImportValidationAttribute> dicItem in dic)
            {
                var propertyInfo = dicItem.Key;
                var excelAttr = dicItem.Value;

                var isExit = headerRow.Cells.Any(t => t.StringCellValue == excelAttr.Name);
                if (!isExit)
                {
                    return new Tuple<bool, string>(false, String.Format("导入的excel中缺少【{0}】列！", excelAttr.Name));
                }

            }

            if (dic.Count > headerRow.Cells.Count)
                return new Tuple<bool, string>(false, "请导入标准的模板");


            return new Tuple<bool, string>(true, "");
        }

        /// <summary>
        /// 验证数据的正确性
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="sheet"></param>
        /// <returns></returns>
        private static Tuple<bool, string> ValidationDatas(Dictionary<PropertyInfo, ExcelImportValidationAttribute> dic,
            ISheet sheet)
        {
            Tuple<bool, string> ret = new Tuple<bool, string>(true, "");

            IRow headerRow = sheet.GetRow(0);
            var rowCount = sheet.LastRowNum;

            var isLoopPass = true;
            for (int i = 1; i <= rowCount; i++)
            {
                var rowCellsList = sheet.GetRow(i).Cells;//某一行所有的单元格
                for (int j = 0; j < sheet.GetRow(i).LastCellNum; j++)
                {
                    var tempValue = "";
                    var cell = sheet.GetRow(i).GetCell(j);
                    if (cell != null)
                        tempValue = cell.ToString();
                    var headerName = headerRow.Cells[j].StringCellValue;//获取表头

                    var keyValue = dic.FirstOrDefault(t => t.Value.Name == headerName);
                    if (!default(KeyValuePair<PropertyInfo, ExcelImportValidationAttribute>).Equals(keyValue))
                    {
                        if (!keyValue.Value.IsAllowEmpty)//表示该单元格不能为空
                        {
                            if (String.IsNullOrEmpty(tempValue))
                            {
                                isLoopPass = false;
                                ret = new Tuple<bool, string>(false, String.Format("导入的excel中第{0}行第{1}列不允许为空！", i + 1, j + 1));
                                break;
                            }

                        }
                    }
                    var isConvertPass = true;
                    if (keyValue.Key.PropertyType == typeof(string))
                    {
                        isConvertPass = GetObject<string>(tempValue);
                    }
                    if (keyValue.Key.PropertyType == typeof(DateTime))
                    {
                        isConvertPass = GetObject<DateTime>(tempValue);
                    }
                    if (keyValue.Key.PropertyType == typeof(int))
                    {
                        isConvertPass = GetObject<int>(tempValue);
                    }
                    if (keyValue.Key.PropertyType == typeof(decimal))
                    {
                        isConvertPass = GetObject<decimal>(tempValue);
                    }

                    if (keyValue.Key.PropertyType == typeof(double))
                    {
                        isConvertPass = GetObject<double>(tempValue);
                    }
                    if (keyValue.Key.PropertyType == typeof(bool))
                    {
                        //isConvertPass = GetObject<bool>(tempValue);
                        isConvertPass = tempValue != "是" || tempValue != "否";
                    }

                    if (!isConvertPass)
                    {
                        var errStr = "数据类型不正确";
                        if (!String.IsNullOrEmpty(keyValue.Value.ErrorDescribtion))
                        {
                            errStr = keyValue.Value.ErrorDescribtion;
                        }
                        ret = new Tuple<bool, string>(false, String.Format("第{0}行第{1}列{2}！", i + 1, j + 1, errStr));
                    }
                }
                if (!isLoopPass) break;
            }
            return ret;
        }

        private static bool GetObject<T>(object value)
        {
            try
            {
                var obj = (T)Convert.ChangeType(value, typeof(T));
                return true;
            }
            catch (Exception e)
            {

                return false;
            }
        }

    }
}